package org.tang.springcloudvv.util;

import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

public class DateUtils {
	
	private static final ThreadLocal<SimpleDateFormat> format1 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
    
    private static final ThreadLocal<SimpleDateFormat> format2 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };
    
    private static final ThreadLocal<SimpleDateFormat> format3 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMdd");
        }
    };
    
    private static final ThreadLocal<SimpleDateFormat> format4 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHHmmssSSS");
        }
    };
    
    private static final ThreadLocal<SimpleDateFormat> format5 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        }
    };
    
    private static final ThreadLocal<SimpleDateFormat> format6 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHHmm");
        }
    };
    
    private static final ThreadLocal<SimpleDateFormat> format7 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHH");
        }
    };

    private static final ThreadLocal<SimpleDateFormat> format8 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMM");
        }
    };
    
    private static final ThreadLocal<SimpleDateFormat> format9 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy.MM.dd");
        }
    };

    private static final ThreadLocal<SimpleDateFormat> format10 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM");
        }
    };

    //Jul 28, 2021 12:00:00 AM
    private static final ThreadLocal<SimpleDateFormat> format11 = ThreadLocal.withInitial(() -> new SimpleDateFormat("MMM d, yyyy K:m:s a", Locale.ENGLISH));
    
    
    private static final ThreadLocal<SimpleDateFormat> format12 = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHHmmss");
        }
    };
    
    public static Date getDate(String dateStr){
        Date result = null;
        try {
        	
            result = format1.get().parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }
    
    public static Date getDateFormat5(String dateStr){
    	Date result = null;
    	try {
    		result = format5.get().parse(dateStr);
    	} catch (ParseException e) {
    		e.printStackTrace();
    	}
    	return result;
    }
    
    public static Date getDateFormat2(String dateStr){
    	Date result = null;
    	try {
    		result = format2.get().parse(dateStr);
    	} catch (ParseException e) {
    		e.printStackTrace();
    	}
    	return result;
    }

    public static String toString(Date date){
        String result = "";
        if(date == null){
            return "";
        }
        result = format2.get().format(date);
        return result;
    }
    
    public static String toStringFormat1(Date date){
        String result = "";
        if(date == null){
            return "";
        }
        result = format1.get().format(date);
        return result;
    }
    
    public static String toStringFormat4(Date date){
    	String result = "";
    	if(date == null){
    		return "";
    	}
    	result = format4.get().format(date);
    	return result;
    }

    /**
     * 获取当前时间戳
     */
    public static Integer getCurrentTimes(){
        return (int) (System.currentTimeMillis() / 1000);
    }

    /**
     * 时间字符串转化为时间戳
     */
    public static Integer getTimestamp(String timeStr) throws ParseException {
        if(StringUtils.isEmpty(timeStr)){
            return null;
        }
        Date date = format2.get().parse(timeStr);
        return (int) (date.getTime() / 1000);
    }

    /**
     * 时间戳转化为字符串  yyyy-MM-dd HH:mm:ss
     */
    public static String getTimeStr(Integer timestamp){
        if(timestamp == null){
            return "";
        }
        Date date = new Date((long)timestamp * 1000);
        return format2.get().format(date);
    }
    
    /**
     * 时间戳转化为字符串       yyyyMMdd
     */
    public static String getTimeStr3(Date date){
        if(date == null){
            return "";
        }
        return format3.get().format(date);
    }
    
    /**
     * 时间戳转化为字符串       yyyyMMdd
     */
    public static String getTimeStr6(Date date){
    	if(date == null){
    		return "";
    	}
    	return format6.get().format(date);
    }
    
    /**
     * 时间戳转化为字符串       yyyyMMdd
     */
    public static String getTimeStr7(Date date){
    	if(date == null){
    		return "";
    	}
    	return format7.get().format(date);
    }


    /**
     * 时间戳转化为字符串       yyyyMMdd
     */
    public static String getTimeStr8(Date date){
        if(date == null){
            return "";
        }
        return format8.get().format(date);
    }

    /**
     * 时间戳转化为字符串  yyyy-MM-dd HH:mm:ss
     */
    public static String getTimeStr2(Date date){
        if(date == null){
            return "";
        }
        return format2.get().format(date);
    }

    public static String getTimeStr5(Date date){
        if(date == null){
            return "";
        }
        return format5.get().format(date);
    }
    
    /**
     * 将日期转化为时间戳
     */
    public static Integer getTimestamp(Date date){
        if(date == null){
            return 0;
        }
        return (int)(date.getTime() / 1000);
    }

    /**
     * 取得指定日期的23:59:59时间点
     */
    public static Date getDate(Date date) {
       Calendar calendar = Calendar.getInstance();
       calendar.setTime(date);
       calendar.set(Calendar.HOUR_OF_DAY, 23);
       calendar.set(Calendar.MINUTE, 59);
       calendar.set(Calendar.SECOND, 59);
       return calendar.getTime();
    }

    /**
     * 取得指定日期的00:00:00时间点
     */
    public static Date getDate2(Date date) {
       Calendar calendar = Calendar.getInstance();
       calendar.setTime(date);
       calendar.set(Calendar.HOUR_OF_DAY, 00);
       calendar.set(Calendar.MINUTE, 00);
       calendar.set(Calendar.SECOND, 00);
       calendar.set(Calendar.MILLISECOND, 0);
       return calendar.getTime();
    }
    
    /**
     * 取得指定日期一年以后的时间
     */
    public static Date getDateAfterOneYear(Date date) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	calendar.add(Calendar.YEAR, +1);
    	return calendar.getTime();
    }

    /**
     * 取得支付宝过期时间  76 天
     */
    public static Date getAliPayOutTime(Date date) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	calendar.set(Calendar.DATE, 76);
    	return calendar.getTime();
    }
    
    /**
     * 取得微信过期时间 351天
     */
    public static Date getWXOutTime(Date date) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	calendar.set(Calendar.DATE, 351);
    	return calendar.getTime();
    }
    
    /**
     * 时间字符串转化为时间戳
     */
    public static Long getLongTimestamp(String timeStr) throws ParseException {
//        Date date = format2.parse(timeStr);
//        return (Long) (date.getTime() / 1000);
        if(!StringUtils.isEmpty(timeStr)) {
        	SimpleDateFormat formatx = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        	 Date date = formatx.parse(timeStr);
        	 return (Long) (date.getTime() / 1000);
        }else {
        	return null;
        }
    }
    
    
    /**
     * 取得指定日期的23:59:59时间点
     */
    public static Date getDayEnd(Date date) {
       Calendar calendar = Calendar.getInstance();
       calendar.setTime(date);
       calendar.set(Calendar.HOUR_OF_DAY, 23);
       calendar.set(Calendar.MINUTE, 59);
       calendar.set(Calendar.SECOND, 59);
       return calendar.getTime();
    }

    /**
     * 取得指定日期的00:00:00时间点
     */
    public static Date getDayBegin(Date date) {
       Calendar calendar = Calendar.getInstance();
       calendar.setTime(date);
       calendar.set(Calendar.HOUR_OF_DAY, 00);
       calendar.set(Calendar.MINUTE, 00);
       calendar.set(Calendar.SECOND, 00);
       //calendar.set(Calendar.MILLISECOND, 0);
       return calendar.getTime();
    }
    
    /**
     * 获取明年的最后一天23:59:59的时间
     */
    public static Date getNextYearEnd(Date date){
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	calendar.add(Calendar.YEAR, 1);
    	calendar.set(Calendar.MONTH,11);
    	calendar.set(Calendar.DAY_OF_MONTH,31);
    	
    	calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        
        
    	return calendar.getTime();
    }
    
    /**
     * 获取明年的這個月的最后一天23:59:59的时间
     */
    public static Date getNextYearThisMonthEnd(Date date){
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	calendar.add(Calendar.YEAR, 1);
    	calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
    	
    	calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        
    	return calendar.getTime();
    }

    /**
     * 获取最后一天23:59:59的时间
     */
    public static Date getMonthEnd_Or_LastDay(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));

        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);

        return calendar.getTime();
    }
    
    
	public static Date getyyyyMMddHHmmss(String dateStr) {
		//SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date result = null;
		try {
			result = format2.get().parse(dateStr);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 返回两个日期的间隔时间  xx天xx小时xx分
	 */
	public static String getInterval(Date startDate,Date endDate){
		if(startDate == null || endDate == null){
			return "";
		}
		if(startDate.getTime() > endDate.getTime()){
			return "";
		}
		
		long intervalTime = endDate.getTime() - startDate.getTime();
		long dTemp = (intervalTime)/ (24 *60 *60 *1000);
		long temp =  intervalTime - dTemp * 24* 60 *60 *1000L;
		
		long hTtemp = temp / (60 * 60 * 1000L);
		temp =  temp - hTtemp * 60 * 60 *1000L;
		
		long mTemp = temp / (60 *1000L);
		return dTemp+"天"+hTtemp+"小时"+mTemp+"分钟";
	}

    public static String yyyy_MM_dd_HH_mm_ss(Date date){
        String result = "";
        if(date == null){
            return "";
        }
        result = format2.get().format(date);
        return result;
    }
    public static String yyyy_MM_dd_HH_mm_ss(LocalDateTime date){
        String result = "";
        if(date == null){
            return "";
        }
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        result = dateTimeFormatter.format(date);
        return result;
    }
	public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }
	
	/*
	 * calendarField取值比如：Calendar.HOUR
	 */
	public static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

	/**
	 * 获取两个时间的时间差(例如:0天0小时4分钟)
	 */
	public static String getTimeDifference(Date beginDate , Date endDate ) {
		Long timeDifference = endDate.getTime() - beginDate.getTime() ;
		
		Long day = timeDifference / ( 1000 * 60 * 60 * 24 ) ;
		Long hour =  (timeDifference -  day * ( 1000 * 60 * 60 * 24 ) ) / (1000 * 60 * 60) ;
		Long minute =( timeDifference - day * ( 1000 * 60 * 60 * 24 ) -  hour * (1000 * 60 * 60)) / (1000 * 60) ;
		String str = day +"天"+hour+"时"+minute+"分" ;
		return str;
	}
	
	/**
	 * 获取当前时间N天之后的时间
	 */
	public static Date getNdayLater(Integer n) {
		Date date = new Date();//取时间 
	    Calendar calendar  =   Calendar.getInstance();
	    calendar.setTime(date); //需要将date数据转移到Calender对象中操作
	    calendar.add(Calendar.DATE, n);//把日期往后增加n天.正数往后推,负数往前移动
	    date=calendar.getTime();   //这个时间就是日期往后推一天的结果 
	    return date ;
	}
	
    /**
     * 取得指定N天日期的23:59:59时间点
     */
    public static Date getNDayEnd(Date date,int n) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	calendar.add(Calendar.DATE,n);
    	calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
    	return calendar.getTime();
    }

    /**
     * 取得指定N天日期的00:00:00时间点
     */
    public static Date getNDayBegin(Date date,int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE,n);
        calendar.set(Calendar.HOUR_OF_DAY, 00);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 00);
        return calendar.getTime();
    }
    
    /*
     * 获取24小时制的小时数
     */
    public static int getHour(Date date) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * @description: 获取指定日期的second秒之前(负数)/之后(正数)的日期
    */
    public static Date getNSecondsLater(Date date,Integer second) {
        Calendar c = new GregorianCalendar();
        //设置参数时间
        c.setTime(date);
        //把日期往后增加SECOND 秒.整数往后推,负数往前移动
        c.add(Calendar.SECOND,second);
        //这个时间就是日期往后推一天的结果
        date=c.getTime();
        return date;
    }


    /**
    * 获取本周一后N天的时间
    */
    public static Date getMondayLater(int n) {
        Calendar weekMondayCal = Calendar.getInstance();
        //获取本周星期一开始时间戳
        weekMondayCal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        weekMondayCal.set(Calendar.MILLISECOND, 0);
        weekMondayCal.set(Calendar.MINUTE, 0);
        weekMondayCal.set(Calendar.SECOND, 0);
        weekMondayCal.set(Calendar.HOUR_OF_DAY, 0);
        weekMondayCal.add(Calendar.DATE, n);
        return weekMondayCal.getTime();
    }
    
    /**
     * 获取本月开始的时间
     */
    public static Date getMonthBeginDate() {
        Calendar cal=Calendar.getInstance();
        cal.add(Calendar.MONTH, 0);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date time=cal.getTime();
        return time;
    }
    
    /**
     * 获取往前那个月1号的日期
     */
    public static Date getMonthBeginDate(int n) {
        Calendar cal=Calendar.getInstance();
        cal.add(Calendar.MONTH, n);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        Date time=cal.getTime();
        return time;
    }

    

    public static boolean verifyDate2(String strValue)
    {
        if (getDateFormat2(strValue) == null)
        {
            return false;
        }
        return true;
    }
    
    public static String toStringformat9(Date date){
        String result = "";
        if(date == null){
            return "";
        }
        result = format9.get().format(date);
        return result;
    }

    public static String toStringformat10(Date date){
        String result = "";
        if(date == null){
            return "";
        }
        result = format10.get().format(date);
        return result;
    }
    public static Date getFormat10(String dateStr) {
        Date result = null;
        try {
            result = format10.get().parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    //2021-06 转格式 2021年06月
    public static String getYYYMM_CN(String date)
    {
        date = date.replace("-","年")+"月";
        return date;
    }
    
    public static Date getDateFormat3(String dateStr){
        Date result = null;
        try {
            result = format3.get().parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static Date parseDate(String dateString){
        if(StringUtils.isEmpty(dateString)){
            return null;
        }
        try {
            //把Jul 8, 2020 12:00:00 AM格式转换为常规的Date格式
            return format11.get().parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    
    public static String toStringformat12(Date date){
        String result = "";
        if(date == null){
            return "";
        }
        result = format12.get().format(date);
        return result;
    }
    
    public static Date getFormat12(String dateStr) {
        Date result = null;
        try {
            result = format12.get().parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static int getDayOfMonth() {
        Calendar cal=Calendar.getInstance();
        cal.setTime(new Date());
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    public static int getDayOfMonth(Date date) {
        Calendar cal=Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

}
